package com.springboot.autoconfigure.oss.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.qiniu.util.StringUtils;
import com.springboot.autoconfigure.oss.config.OssConfigPropertis;
import com.springboot.autoconfigure.oss.config.PublicMetaConfig;
import com.springboot.autoconfigure.oss.config.UpYunOssPropertis;
import com.springboot.autoconfigure.oss.model.FileInfo;
import com.springboot.autoconfigure.oss.model.FileOssOperationStatus;
import com.springboot.autoconfigure.oss.model.FileUploadStatus;
import com.springboot.autoconfigure.oss.service.AbstractInitClientServer;
import com.springboot.autoconfigure.oss.service.FileResolveService;
import com.springboot.autoconfigure.oss.service.OssApiService;
import com.upyun.RestManager;
import com.upyun.UpException;
import okhttp3.Response;
import org.springframework.beans.factory.InitializingBean;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.*;

/**
 * 又拍云存储
 */
public class UpyunOssApiServiceImpl extends FileResolveService implements OssApiService<UpYunOssPropertis>, AbstractInitClientServer<String>, InitializingBean {

    private static RestManager manager;


    private UpYunOssPropertis upYunOssPropertis;
    private OssConfigPropertis ossConfigPropertis;

    @Override
    public String getinit() {

        return null;
    }

    @Override
    public void getUploadUrl(FileUploadStatus fileUploadStatus, String uploadResponseInfo) {

    }

    public UpyunOssApiServiceImpl(UpYunOssPropertis upYunOssPropertis, OssConfigPropertis ossConfigPropertis) {
        this.upYunOssPropertis = upYunOssPropertis;
        this.ossConfigPropertis = ossConfigPropertis;
        manager = new RestManager(upYunOssPropertis.getBucketName(), upYunOssPropertis.getUserName(), upYunOssPropertis.getPassword());
//        manager.setApiDomain("https://files.zaier8023.com.cn");
        manager.setApiDomain(RestManager.ED_AUTO);
    }

    @Override
    public FileUploadStatus uploadFile(URL url) {
        File fileByUrl = null;
        FileUploadStatus fileUploadStatus=null;
        try {
             fileByUrl = getFileByUrl(url);
            fileUploadStatus= uploadFile(fileByUrl);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }finally {
            fileByUrl.delete();
        }

        return fileUploadStatus;
    }

    @Override
    public FileUploadStatus uploadFile(URL url, String filePrix) {
        try {
            return  getFileUploadStatus(getFileByUrl(url),filePrix);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (UpException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     *  // 例1：上传纯文本内容，自动创建父级目录
     *         Map<String, String> params = new HashMap<String, String>();
     *   // 设置待上传文件的 Content-MD5 值
     *         // 如果又拍云服务端收到的文件MD5值与用户设置的不一致，将回报 406 NotAcceptable 错误
     * //        params.put(RestManager.PARAMS.CONTENT_MD5.getValue(), UpYunUtils.md5(file, 1024));
     *         // 设置待上传文件的"访问密钥"
     *         // 注意：
     *         // 仅支持图片空！，设置密钥后，无法根据原文件URL直接访问，需带URL后面加上（缩略图间隔标志符+密钥）进行访问
     *         // 举例：
     *         // 如果缩略图间隔标志符为"!"，密钥为"bac"，上传文件路径为"/folder/test.jpg"，
     *         // 那么该图片的对外访问地址为：http://空间域名 /folder/test.jpg!bac
     * //        params.put(RestManager.PARAMS.CONTENT_SECRET.getValue(), "bac");
     * @param file
     * @return
     */
    @Override
    public FileUploadStatus uploadFile(File file) {
        try {
            return getFileUploadStatus(file,null);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (UpException e) {
            throw new RuntimeException(e);
        }
    }

   

    private FileUploadStatus getFileUploadStatus(File file,String filePrix,String... customizefileName) throws IOException, UpException {
        Map<String, String> params = new HashMap<String, String>();
        StringBuilder strBuilder = new StringBuilder();
        if (!StrUtil.isBlank(ossConfigPropertis.getFolderPathName())){
            strBuilder.append(ossConfigPropertis.getFolderPathName());
            strBuilder.append(PublicMetaConfig.FILEPATH_SPLITMARK);
        }
        String tmpfilePrix=filePrix;
        //配置会优先覆盖
        if (!StrUtil.isBlank(ossConfigPropertis.getFilePrefix())){
            filePrix = ossConfigPropertis.getFilePrefix();
        }
        if (!StrUtil.isBlank(tmpfilePrix)){
            filePrix = filePrix + tmpfilePrix;
        }
        if (StringUtils.isNullOrEmpty(filePrix)){
            strBuilder.append(filePrix);
            // 文件名分割符
            strBuilder.append(ossConfigPropertis.getFilePathSplit());
        }
        String fileName= cn.hutool.core.lang.UUID.randomUUID().toString();
        if (customizefileName.length > 0){
            fileName=customizefileName[0];
        }
        strBuilder.append(fileName);
        strBuilder.append(file.getName());
        String fileKey=strBuilder.toString();
        Response result = manager.writeFile(fileKey, file, params);
        System.out.println(result.request().toString());
        return FileUploadStatus.builder().fileKey(fileKey).url(findFileByKey(fileKey).getUrl()).success(true).build();
    }

    @Override
    public FileUploadStatus uploadAbsoulteFilePath(File file, String filePath) {
        Map<String, String> params = new HashMap<String, String>();
        String fileKey=filePath+File.separator+ UUID.randomUUID()+file.getName();
        Response result = null;
        try {
            result = manager.writeFile(fileKey, file, params);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (UpException e) {
            throw new RuntimeException(e);
        }
        System.out.println(result.request().toString());
        return  FileUploadStatus.builder().fileKey(fileKey).success(true).build();
    }

    @Override
    public FileUploadStatus uploadFile(File file, String fileName) {
        try {
            return getFileUploadStatus(file,null,fileName);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (UpException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public FileUploadStatus uploadFileAndCallBack(File file, String callbackUrl) {
        return null;
    }

    @Override
    public List<String> findFile(String... fileNames) {
        if (fileNames==null || fileNames.length==0)return null;
        ArrayList<String> result = new ArrayList<>();
        for (String fileName : fileNames) {
            try {
                Response fileInfo = manager.getFileInfo(fileName);
                if (fileInfo.code() != 200){
                    throw new IllegalArgumentException();
                }
                System.out.println(fileInfo.body().contentLength());
            } catch (IOException e) {
                throw new RuntimeException(e);
            } catch (UpException e) {
                throw new RuntimeException(e);
            }
        }
        return null;
    }

    @Override
    public FileOssOperationStatus delFile(String... fileNames) {
        for (String fileName : fileNames) {
            try {
                Response response = manager.deleteFile(fileName, null);
            } catch (IOException e) {
                throw new RuntimeException(e);
            } catch (UpException e) {
                throw new RuntimeException(e);
            }
        }

        return FileOssOperationStatus.suceess();
    }

    @Override
    public FileUploadStatus findFileByKey(String fileKey) {
        String domain = upYunOssPropertis.getDomain();
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(domain);
        stringBuffer.append(fileKey);
        return FileUploadStatus.builder().success(true).fileKey(fileKey).url(stringBuffer.toString()).build();
    }

    @Override
    public List<FileInfo> getBucketSpaceFile(String prefix, int limit) {
        HashMap<String, String> param = new HashMap<>();
        param.put(RestManager.PARAMS.X_LIST_LIMIT.getValue(),String.valueOf(limit));
        param.put(RestManager.PARAMS.ACCEPT.getValue(),"application/json");
        ArrayList<FileInfo> result = new ArrayList<>();
        try {
            Response response = manager.readDirIter(prefix, param);
            String returnJson = new String(response.body().bytes());
            JSONObject jsonObject = JSONUtil.parseObj(returnJson);
            JSONArray files = JSONUtil.parseArray(jsonObject.getStr("files"));
            for (Object file : files) {
                JSONObject jsonObject1 = JSONUtil.parseObj(file);
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append(prefix);
                if (!prefix.endsWith("/")){
                    stringBuilder.append("/");
                }
                stringBuilder.append(jsonObject1.getStr("name"));
                System.out.println(stringBuilder.toString());
                FileInfo fileInfo = new FileInfo();
                fileInfo.setFileKey(stringBuilder.toString());
                result.add(fileInfo);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (UpException e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        manager = new RestManager(upYunOssPropertis.getBucketName(), upYunOssPropertis.getUserName(), upYunOssPropertis.getPassword());
        manager.setApiDomain(RestManager.ED_AUTO);
    }


}
